from PySide6.QtGui import QFont
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox,
                               QFormLayout, QLabel, QDoubleSpinBox, QComboBox,
                               QSpinBox, QLineEdit, QCheckBox, QPushButton, QFrame,
                               QTabWidget, QTableWidget, QTableWidgetItem, QHeaderView)
from PySide6.QtCore import Qt, Signal


class SettingsPanel(QWidget):
    # 定义信号
    globalSettingsChanged = Signal(dict)
    nodeParameterChanged = Signal(str, str, object)  # nodeId, parameterName, value
    nodeNameChanged = Signal(str, str)  # nodeId, newName

    def __init__(self):
        super().__init__()
        self.currentNode = None
        self.parameterWidgets = {}

        # 先定义所有必要的属性
        self.globalGroup = None
        self.nodeInfoGroup = None
        self.nodeSettingsGroup = None
        self.nodeSettingsLayout = None

        self.initUI()

    def initUI(self):
        layout = QVBoxLayout(self)

        # 全局设置区域
        self.globalGroup = QGroupBox("全局设置")
        globalLayout = QFormLayout()

        self.sampleRateCombo = QComboBox()
        self.sampleRateCombo.addItems(["44100", "48000", "88200", "96000"])
        self.sampleRateCombo.currentTextChanged.connect(self.onGlobalSettingChanged)
        globalLayout.addRow("采样率 (Hz):", self.sampleRateCombo)

        self.bufferSizeSpin = QSpinBox()
        self.bufferSizeSpin.setRange(64, 4096)
        self.bufferSizeSpin.setValue(512)
        self.bufferSizeSpin.valueChanged.connect(self.onGlobalSettingChanged)
        globalLayout.addRow("缓冲区大小:", self.bufferSizeSpin)

        self.channelCountCombo = QComboBox()
        self.channelCountCombo.addItems(["1 (单声道)", "2 (立体声)"])
        self.channelCountCombo.currentIndexChanged.connect(self.onGlobalSettingChanged)
        globalLayout.addRow("声道数:", self.channelCountCombo)

        # 新增音频设备设置
        self.setupAudioDeviceSettings(globalLayout)

        self.globalGroup.setLayout(globalLayout)

        # 节点信息区域
        self.nodeInfoGroup = QGroupBox("节点信息")
        self.nodeInfoLayout = QFormLayout()

        # 节点名称 - 可编辑的文本框
        self.nodeNameEdit = QLineEdit()
        self.nodeNameEdit.setPlaceholderText("输入节点名称...")
        self.nodeNameEdit.editingFinished.connect(self.onNodeNameChanged)
        self.nodeInfoLayout.addRow("节点名称:", self.nodeNameEdit)

        # 节点类型 - 只读标签
        self.nodeTypeLabel = QLabel()
        self.nodeInfoLayout.addRow("节点类型:", self.nodeTypeLabel)

        # 节点UUID - 只读标签
        self.nodeUuidLabel = QLabel()
        font = QFont()
        font.setPointSize(8)
        self.nodeUuidLabel.setFont(font)
        self.nodeUuidLabel.setWordWrap(True)
        self.nodeInfoLayout.addRow("节点UUID:", self.nodeUuidLabel)

        # 复制UUID按钮
        self.copyUuidButton = QPushButton("复制UUID")
        self.copyUuidButton.clicked.connect(self.copyNodeUuid)
        self.nodeInfoLayout.addRow("", self.copyUuidButton)

        # 端口信息 - 只读标签
        self.inputPortsLabel = QLabel()
        self.nodeInfoLayout.addRow("输入端口:", self.inputPortsLabel)

        self.outputPortsLabel = QLabel()
        self.nodeInfoLayout.addRow("输出端口:", self.outputPortsLabel)

        self.nodeInfoGroup.setLayout(self.nodeInfoLayout)

        # 节点设置区域
        self.nodeSettingsGroup = QGroupBox("节点设置")
        self.nodeSettingsLayout = QFormLayout()
        self.nodeSettingsGroup.setLayout(self.nodeSettingsLayout)

        layout.addWidget(self.globalGroup)
        layout.addWidget(self.nodeInfoGroup)
        layout.addWidget(self.nodeSettingsGroup)
        layout.addStretch()

        # 初始显示全局设置
        self.showGlobalSettings()

    def setupAudioDeviceSettings(self, layout):
        """设置音频设备配置界面 - 使用表格形式"""
        # 音频设备管理标题
        audioTitle = QLabel("音频设备映射管理")
        audioTitle.setStyleSheet("font-weight: bold; font-size: 14px; margin-top: 10px;")
        layout.addRow(audioTitle)

        # 刷新设备按钮
        self.refreshDevicesButton = QPushButton("重新扫描音频设备")
        self.refreshDevicesButton.clicked.connect(self.refreshAudioDevices)
        layout.addRow("", self.refreshDevicesButton)

        # 创建选项卡控件来分别管理输入和输出
        self.audioTabs = QTabWidget()

        # 输入设备选项卡
        self.inputTab = QWidget()
        self.setupInputDeviceTable(self.inputTab)
        self.audioTabs.addTab(self.inputTab, "输入设备映射")

        # 输出设备选项卡
        self.outputTab = QWidget()
        self.setupOutputDeviceTable(self.outputTab)
        self.audioTabs.addTab(self.outputTab, "输出设备映射")

        layout.addRow(self.audioTabs)

    def setupInputDeviceTable(self, parent):
        """设置输入设备表格"""
        layout = QVBoxLayout(parent)

        # 表格标题
        inputTitle = QLabel("输入设备映射表 (内部ID → 物理设备)")
        inputTitle.setStyleSheet("font-weight: bold; margin-bottom: 10px;")
        layout.addWidget(inputTitle)

        # 创建表格
        self.inputTable = QTableWidget()
        self.inputTable.setColumnCount(3)
        self.inputTable.setHorizontalHeaderLabels(["内部ID", "物理设备", "操作"])

        # 设置表格属性
        self.inputTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.inputTable.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.inputTable.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)

        # 添加按钮
        buttonLayout = QHBoxLayout()
        addInputButton = QPushButton("添加输入映射")
        addInputButton.clicked.connect(self.addInputMapping)
        buttonLayout.addWidget(addInputButton)

        buttonLayout.addStretch()
        layout.addWidget(self.inputTable)
        layout.addLayout(buttonLayout)

    def setupOutputDeviceTable(self, parent):
        """设置输出设备表格"""
        layout = QVBoxLayout(parent)

        # 表格标题
        outputTitle = QLabel("输出设备映射表 (内部ID → 物理设备)")
        outputTitle.setStyleSheet("font-weight: bold; margin-bottom: 10px;")
        layout.addWidget(outputTitle)

        # 创建表格
        self.outputTable = QTableWidget()
        self.outputTable.setColumnCount(3)
        self.outputTable.setHorizontalHeaderLabels(["内部ID", "物理设备", "操作"])

        # 设置表格属性
        self.outputTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.outputTable.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.outputTable.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)

        # 添加按钮
        buttonLayout = QHBoxLayout()
        addOutputButton = QPushButton("添加输出映射")
        addOutputButton.clicked.connect(self.addOutputMapping)
        buttonLayout.addWidget(addOutputButton)

        buttonLayout.addStretch()
        layout.addWidget(self.outputTable)
        layout.addLayout(buttonLayout)

    def refreshAudioDevices(self):
        """刷新音频设备列表并更新表格"""
        try:
            # 获取音频设备管理器
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                device_manager = main_window.audioDeviceManager

                # 重新扫描设备
                device_manager.scan_devices()

                # 更新输入设备表格
                self.updateInputTable()

                # 更新输出设备表格
                self.updateOutputTable()

                # 显示状态消息
                try:
                    if hasattr(main_window, 'statusBar') and main_window.statusBar():
                        input_count = len(device_manager.input_devices)
                        output_count = len(device_manager.output_devices)
                        main_window.statusBar().showMessage(
                            f"已扫描到 {input_count} 个输入设备和 {output_count} 个输出设备",
                            3000
                        )
                except:
                    pass

        except Exception as e:
            print(f"刷新音频设备时出错: {e}")

    def updateInputTable(self):
        """更新输入设备表格"""
        try:
            main_window = self.window()
            if not hasattr(main_window, 'audioDeviceManager') or not main_window.audioDeviceManager:
                return

            device_manager = main_window.audioDeviceManager

            # 获取输入映射
            input_mapping = device_manager.get_input_mapping()
            available_inputs = device_manager.get_available_inputs()

            # 设置表格行数
            self.inputTable.setRowCount(len(input_mapping))

            # 填充表格
            for row, (internal_id, device_id, device_name) in enumerate(input_mapping):
                # 内部ID列（只读）
                id_item = QTableWidgetItem(str(internal_id))
                id_item.setFlags(id_item.flags() & ~Qt.ItemIsEditable)
                self.inputTable.setItem(row, 0, id_item)

                # 设备选择列（下拉框）
                combo = QComboBox()
                combo.addItem("未选择", "")
                for device in available_inputs:
                    combo.addItem(f"{device['name']} ({device['id']})", device['id'])

                # 设置当前选择的设备
                current_index = combo.findData(device_id)
                if current_index >= 0:
                    combo.setCurrentIndex(current_index)

                # 连接信号
                combo.currentIndexChanged.connect(
                    lambda index, combo=combo, internal_id=internal_id:
                    self.onInputDeviceChanged(internal_id, combo.currentData())
                )

                self.inputTable.setCellWidget(row, 1, combo)

                # 操作列（删除按钮）
                delete_button = QPushButton("删除")
                delete_button.clicked.connect(
                    lambda checked, internal_id=internal_id:
                    self.removeInputMapping(internal_id)
                )
                self.inputTable.setCellWidget(row, 2, delete_button)

            # 应用当前主题到表格
            self.applyCurrentThemeToTable(self.inputTable)

        except Exception as e:
            print(f"更新输入表格时出错: {e}")

    def updateOutputTable(self):
        """更新输出设备表格"""
        try:
            main_window = self.window()
            if not hasattr(main_window, 'audioDeviceManager') or not main_window.audioDeviceManager:
                return

            device_manager = main_window.audioDeviceManager

            # 获取输出映射
            output_mapping = device_manager.get_output_mapping()
            available_outputs = device_manager.get_available_outputs()

            # 设置表格行数
            self.outputTable.setRowCount(len(output_mapping))

            # 填充表格
            for row, (internal_id, device_id, device_name) in enumerate(output_mapping):
                # 内部ID列（只读）
                id_item = QTableWidgetItem(str(internal_id))
                id_item.setFlags(id_item.flags() & ~Qt.ItemIsEditable)
                self.outputTable.setItem(row, 0, id_item)

                # 设备选择列（下拉框）
                combo = QComboBox()
                combo.addItem("未选择", "")
                for device in available_outputs:
                    combo.addItem(f"{device['name']} ({device['id']})", device['id'])

                # 设置当前选择的设备
                current_index = combo.findData(device_id)
                if current_index >= 0:
                    combo.setCurrentIndex(current_index)

                # 连接信号
                combo.currentIndexChanged.connect(
                    lambda index, combo=combo, internal_id=internal_id:
                    self.onOutputDeviceChanged(internal_id, combo.currentData())
                )

                self.outputTable.setCellWidget(row, 1, combo)

                # 操作列（删除按钮）
                delete_button = QPushButton("删除")
                delete_button.clicked.connect(
                    lambda checked, internal_id=internal_id:
                    self.removeOutputMapping(internal_id)
                )
                self.outputTable.setCellWidget(row, 2, delete_button)

            # 应用当前主题到表格
            self.applyCurrentThemeToTable(self.outputTable)

        except Exception as e:
            print(f"更新输出表格时出错: {e}")

    def applyCurrentThemeToTable(self, table):
        """应用当前主题到表格"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'currentTheme'):
                theme = main_window.currentTheme

                # 设置交替行颜色
                if theme == "light":
                    table.setAlternatingRowColors(True)
                    table.setStyleSheet("""
                        QTableWidget {
                            alternate-background-color: #f8f8f8;
                        }
                    """)
                else:
                    table.setAlternatingRowColors(True)
                    table.setStyleSheet("""
                        QTableWidget {
                            alternate-background-color: #3a3a3a;
                        }
                    """)
        except Exception as e:
            print(f"应用主题到表格时出错: {e}")

    def addInputMapping(self):
        """添加新的输入映射"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                new_id = main_window.audioDeviceManager.add_input_mapping()
                self.updateInputTable()
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"添加输入映射时出错: {e}")

    def addOutputMapping(self):
        """添加新的输出映射"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                new_id = main_window.audioDeviceManager.add_output_mapping()
                self.updateOutputTable()
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"添加输出映射时出错: {e}")

    def removeInputMapping(self, internal_id: int):
        """移除输入映射"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                main_window.audioDeviceManager.remove_input_mapping(internal_id)
                self.updateInputTable()
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"移除输入映射时出错: {e}")

    def removeOutputMapping(self, internal_id: int):
        """移除输出映射"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                main_window.audioDeviceManager.remove_output_mapping(internal_id)
                self.updateOutputTable()
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"移除输出映射时出错: {e}")

    def onInputDeviceChanged(self, internal_id: int, device_id: str):
        """输入设备选择改变"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                main_window.audioDeviceManager.update_input_mapping(internal_id, device_id)
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"更新输入设备映射时出错: {e}")

    def onOutputDeviceChanged(self, internal_id: int, device_id: str):
        """输出设备选择改变"""
        try:
            main_window = self.window()
            if hasattr(main_window, 'audioDeviceManager') and main_window.audioDeviceManager:
                main_window.audioDeviceManager.update_output_mapping(internal_id, device_id)
                self.onGlobalSettingChanged()  # 触发设置改变信号
        except Exception as e:
            print(f"更新输出设备映射时出错: {e}")

    def onNodeNameChanged(self):
        """节点名称改变事件"""
        if self.currentNode:
            new_name = self.nodeNameEdit.text()
            if new_name and new_name.strip():
                # 直接设置节点名称
                self.currentNode.setNodeName(new_name)
                # 标记未保存更改 - 通过窗口层级
                try:
                    main_window = self.window()
                    if hasattr(main_window, 'markUnsavedChanges'):
                        main_window.markUnsavedChanges()
                except Exception as e:
                    print(f"标记未保存更改时出错: {e}")

    def updateNodeInfo(self, node):
        """更新节点信息显示"""
        # 节点名称
        self.nodeNameEdit.setText(node.getDisplayName())

        # 节点类型
        self.nodeTypeLabel.setText(node.nodeType)

        # 节点UUID（在节点信息区域显示，不需要额外区域）
        self.nodeUuidLabel.setText(node.nodeId)

        # 输入端口信息
        inputPorts = list(node.inputPorts.keys())
        self.inputPortsLabel.setText(", ".join(inputPorts) if inputPorts else "无")

        # 输出端口信息
        outputPorts = list(node.outputPorts.keys())
        self.outputPortsLabel.setText(", ".join(outputPorts) if outputPorts else "无")

    def copyNodeUuid(self):
        """复制节点UUID到剪贴板"""
        if self.currentNode:
            from PySide6.QtWidgets import QApplication
            clipboard = QApplication.clipboard()
            clipboard.setText(self.currentNode.nodeId)

            # 修复状态栏消息显示 - 使用更安全的方式访问主窗口
            try:
                # 尝试通过窗口层级找到主窗口
                main_window = self.window()
                if hasattr(main_window, 'statusBar') and main_window.statusBar():
                    main_window.statusBar().showMessage(f"已复制节点UUID: {self.currentNode.nodeId}", 3000)
            except:
                # 如果无法访问状态栏，只打印到控制台
                pass

            print(f"已复制节点UUID: {self.currentNode.nodeId}")

    def getGlobalSettings(self):
        """获取全局设置"""
        settings = {
            'sampleRate': int(self.sampleRateCombo.currentText()),
            'bufferSize': self.bufferSizeSpin.value(),
            'channelCount': self.channelCountCombo.currentIndex() + 1
        }
        return settings

    def setGlobalSettings(self, settings):
        """设置全局设置"""
        # 原有设置代码...
        if 'sampleRate' in settings:
            sampleRateText = str(settings['sampleRate'])
            index = self.sampleRateCombo.findText(sampleRateText)
            if index >= 0:
                self.sampleRateCombo.setCurrentIndex(index)

        if 'bufferSize' in settings:
            self.bufferSizeSpin.setValue(settings['bufferSize'])

        if 'channelCount' in settings:
            channelIndex = settings['channelCount'] - 1
            if 0 <= channelIndex < self.channelCountCombo.count():
                self.channelCountCombo.setCurrentIndex(channelIndex)

    def onGlobalSettingChanged(self):
        """全局设置改变"""
        self.globalSettingsChanged.emit(self.getGlobalSettings())

    def showGlobalSettings(self):
        """显示全局设置"""
        self.currentNode = None
        self.nodeInfoGroup.hide()
        if self.nodeSettingsGroup:  # 安全检查
            self.nodeSettingsGroup.hide()
        self.globalGroup.show()

    def showNodeSettings(self, node):
        """显示节点设置"""
        self.currentNode = node
        self.globalGroup.hide()
        self.nodeInfoGroup.show()

        # 确保 nodeSettingsGroup 存在
        if hasattr(self, 'nodeSettingsGroup') and self.nodeSettingsGroup:
            self.nodeSettingsGroup.show()
        else:
            # 如果不存在，创建它
            self.nodeSettingsGroup = QGroupBox("节点设置")
            self.nodeSettingsLayout = QFormLayout()
            self.nodeSettingsGroup.setLayout(self.nodeSettingsLayout)
            # 找到布局并添加
            layout = self.layout()
            if layout:
                layout.insertWidget(2, self.nodeSettingsGroup)

        # 更新节点信息
        self.updateNodeInfo(node)

        # 清除之前的控件
        self.clearNodeSettings()

        # 添加参数控件
        parameters = node.nodeData.get('parameters', {})
        self.parameterWidgets = {}

        for paramName, paramConfig in parameters.items():
            paramType = paramConfig.get('type', 'float')
            defaultValue = node.getParameterValue(paramName)
            minValue = paramConfig.get('min', 0.0)
            maxValue = paramConfig.get('max', 1.0)

            if paramType == 'float':
                spinBox = QDoubleSpinBox()
                spinBox.setRange(minValue, maxValue)
                spinBox.setValue(defaultValue)
                spinBox.setSingleStep(0.1)
                spinBox.valueChanged.connect(
                    lambda value, pn=paramName: self.onNodeParameterChanged(pn, value)
                )
                self.nodeSettingsLayout.addRow(f"{paramName}:", spinBox)
                self.parameterWidgets[paramName] = spinBox

            elif paramType == 'int':
                spinBox = QSpinBox()
                spinBox.setRange(int(minValue), int(maxValue))
                spinBox.setValue(int(defaultValue))
                spinBox.valueChanged.connect(
                    lambda value, pn=paramName: self.onNodeParameterChanged(pn, value)
                )
                self.nodeSettingsLayout.addRow(f"{paramName}:", spinBox)
                self.parameterWidgets[paramName] = spinBox

            elif paramType == 'choice':
                comboBox = QComboBox()
                choices = paramConfig.get('choices', [])
                comboBox.addItems(choices)
                if defaultValue in choices:
                    comboBox.setCurrentText(str(defaultValue))
                elif choices:
                    comboBox.setCurrentIndex(0)
                comboBox.currentTextChanged.connect(
                    lambda value, pn=paramName: self.onNodeParameterChanged(pn, value)
                )
                self.nodeSettingsLayout.addRow(f"{paramName}:", comboBox)
                self.parameterWidgets[paramName] = comboBox

            elif paramType == 'bool':
                checkBox = QCheckBox()
                checkBox.setChecked(bool(defaultValue))
                checkBox.stateChanged.connect(
                    lambda state, pn=paramName: self.onNodeParameterChanged(pn, bool(state))
                )
                self.nodeSettingsLayout.addRow(f"{paramName}:", checkBox)
                self.parameterWidgets[paramName] = checkBox

            elif paramType == 'string':
                lineEdit = QLineEdit()
                lineEdit.setText(str(defaultValue))
                lineEdit.textChanged.connect(
                    lambda text, pn=paramName: self.onNodeParameterChanged(pn, text)
                )
                self.nodeSettingsLayout.addRow(f"{paramName}:", lineEdit)
                self.parameterWidgets[paramName] = lineEdit

        # 如果是波形查看器节点或FFT查看器节点，添加打开显示窗口按钮
        if node.nodeType == 'waveform_viewer' or node.nodeType == 'fft_viewer':
            # 添加分隔线
            separator = QFrame()
            separator.setFrameShape(QFrame.HLine)
            separator.setFrameShadow(QFrame.Sunken)
            self.nodeSettingsLayout.addRow(separator)

            # 添加显示控制标题
            if node.nodeType == 'waveform_viewer':
                displayTitle = QLabel("波形显示控制")
            else:
                displayTitle = QLabel("频谱显示控制")
            displayTitle.setStyleSheet("font-weight: bold; font-size: 12px;")
            self.nodeSettingsLayout.addRow(displayTitle)

            # 添加打开显示窗口按钮
            if node.nodeType == 'waveform_viewer':
                buttonText = "打开波形显示窗口"
            else:
                buttonText = "打开频谱显示窗口"
            
            openDisplayBtn = QPushButton(buttonText)
            openDisplayBtn.clicked.connect(self._open_display_window)
            # 保存按钮引用，用于后续控制启用/禁用状态
            self.openDisplayButton = openDisplayBtn
            self.nodeSettingsLayout.addRow("", openDisplayBtn)
            
            # 保存当前节点类型
            self.currentNodeType = node.nodeType

    def clearNodeSettings(self):
        """清除节点设置控件"""
        if not hasattr(self, 'nodeSettingsLayout') or not self.nodeSettingsLayout:
            return

        # 使用正确的属性名：nodeSettingsLayout
        for i in reversed(range(self.nodeSettingsLayout.count())):
            item = self.nodeSettingsLayout.itemAt(i)
            if item.widget():
                item.widget().deleteLater()
            elif item.layout():
                # 递归删除子布局中的控件
                self.clearLayout(item.layout())

    def clearLayout(self, layout):
        """递归清除布局中的控件"""
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self.clearLayout(item.layout())

    def onNodeParameterChanged(self, parameterName, value):
        """节点参数改变回调"""
        if self.currentNode:
            self.currentNode.setParameterValue(parameterName, value)
            self.nodeParameterChanged.emit(
                self.currentNode.nodeId,
                parameterName,
                value
            )

    def updateNodeParameterWidgets(self, node):
        """更新节点参数控件显示的值"""
        if node == self.currentNode:
            for paramName, widget in self.parameterWidgets.items():
                currentValue = node.getParameterValue(paramName)
                if isinstance(widget, QDoubleSpinBox):
                    widget.setValue(float(currentValue))
                elif isinstance(widget, QSpinBox):
                    widget.setValue(int(currentValue))
                elif isinstance(widget, QComboBox):
                    if str(currentValue) in [widget.itemText(i) for i in range(widget.count())]:
                        widget.setCurrentText(str(currentValue))
                elif isinstance(widget, QCheckBox):
                    widget.setChecked(bool(currentValue))
                elif isinstance(widget, QLineEdit):
                    widget.setText(str(currentValue))

    def _open_display_window(self):
        """打开显示窗口（波形或频谱）"""
        if not hasattr(self, 'currentNode') or not self.currentNode:
            return

        node_id = self.currentNode.nodeId
        main_window = self.window()
        node_type = self.currentNode.nodeType

        # 检查主窗口是否有波形窗口管理
        if hasattr(main_window, 'waveform_windows'):
            # 如果窗口已经存在，则激活它
            if node_id in main_window.waveform_windows:
                window = main_window.waveform_windows[node_id]
                window.show()
                window.activateWindow()
                window.raise_()
                print(f"激活现有{'波形' if node_type == 'waveform_viewer' else '频谱'}窗口: {node_id}")
            else:
                # 根据节点类型创建相应的窗口
                if node_type == 'waveform_viewer' and hasattr(main_window, '_create_waveform_window'):
                    main_window._create_waveform_window(self.currentNode)
                    print(f"创建新波形窗口: {node_id}")
                elif node_type == 'fft_viewer' and hasattr(main_window, '_create_fft_window'):
                    main_window._create_fft_window(self.currentNode)
                    print(f"创建新频谱窗口: {node_id}")
                else:
                    print(f"错误: 主窗口没有创建{node_type}窗口的方法")
        else:
            print("错误: 主窗口没有 waveform_windows 属性")
    
    def setEnabledForWaveformViewers(self, enabled):
        """启用或禁用波形查看器节点的设置控件
        
        Args:
            enabled: 是否启用设置控件
        """
        try:
            # 只在处理进程初始化或节点设置变更时调用，避免频繁更新
            
            # 检查是否为波形查看器或FFT查看器节点
            is_viewer_node = False
            if hasattr(self, 'currentNode') and self.currentNode:
                is_viewer_node = self.currentNode.nodeType in ['waveform_viewer', 'fft_viewer']
            
            # 只有当当前节点是查看器节点时才更新控件状态
            if is_viewer_node:
                # 安全地更新参数控件
                if hasattr(self, 'parameterWidgets'):
                    for paramName, widget in self.parameterWidgets.items():
                        if hasattr(widget, 'setEnabled'):
                            widget.setEnabled(enabled)
                
                # 确保打开窗口按钮始终可用
                if hasattr(self, 'openDisplayButton') and self.openDisplayButton:
                    self.openDisplayButton.setEnabled(True)
                
                # 处理状态标签
                if hasattr(self, 'statusLabel') and self.statusLabel:
                    # 更新现有标签
                    if enabled:
                        self.statusLabel.setText("设置已启用")
                        self.statusLabel.setStyleSheet("color: green; font-size: 10px; font-style: italic;")
                    else:
                        self.statusLabel.setText("设置已锁定（处理运行中）")
                        self.statusLabel.setStyleSheet("color: orange; font-size: 10px; font-style: italic;")
                else:
                    # 创建新标签（只在需要时）
                    self.statusLabel = QLabel("设置已锁定（处理运行中）" if not enabled else "设置已启用")
                    self.statusLabel.setStyleSheet("color: orange; font-size: 10px; font-style: italic;" if not enabled else "color: green; font-size: 10px; font-style: italic;")
                    
                    # 安全地添加到布局
                    if hasattr(self, 'nodeSettingsLayout') and self.nodeSettingsLayout:
                        self.nodeSettingsLayout.addRow("", self.statusLabel)
        except Exception as e:
            print(f"更新设置面板状态时出错: {e}")

    def addSubsystemUUIDSection(self, node):
        """添加子系统UUID显示区域"""
        # 创建分隔线
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        self.nodeSettingsLayout.addRow(separator)

        # 添加子系统UUID标题
        uuidTitle = QLabel("子系统UUID")
        uuidTitle.setStyleSheet("font-weight: bold; font-size: 12px;")
        self.nodeSettingsLayout.addRow(uuidTitle)

        # 创建UUID显示和复制按钮的布局
        uuidWidget = QWidget()
        uuidLayout = QHBoxLayout(uuidWidget)
        uuidLayout.setContentsMargins(0, 0, 0, 0)

        # UUID显示标签
        uuidLabel = QLabel(node.nodeId)
        uuidLabel.setWordWrap(True)
        uuidLabel.setStyleSheet("""
            QLabel {
                background-color: #f0f0f0;
                border: 1px solid #ccc;
                border-radius: 3px;
                padding: 5px;
                font-family: monospace;
                font-size: 10px;
            }
        """)

        # 复制UUID按钮
        copyUuidButton = QPushButton("复制")
        copyUuidButton.setFixedWidth(60)
        copyUuidButton.clicked.connect(lambda: self.copyNodeUuid())

        uuidLayout.addWidget(uuidLabel, 1)
        uuidLayout.addWidget(copyUuidButton)

        self.nodeSettingsLayout.addRow("UUID:", uuidWidget)

        # 添加说明文本
        description = QLabel("此UUID用于唯一标识该子系统节点")
        description.setStyleSheet("font-size: 10px; color: #666;")
        description.setWordWrap(True)
        self.nodeSettingsLayout.addRow("", description)